home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / sendmail / sendmail-5.65c+IDA-1.4.4.1 / ida / aux / rmail.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-01  |  7.5 KB  |  328 lines

  1. /*
  2. **  RMAIL -- Receive remote mail requests.
  3. **  Copyright (c) 1987 Lennart Lovstrand
  4. **  CIS Dept, Univ of Linkoping, Sweden
  5. **
  6. **  Use it, abuse it, but don't sell it.
  7. **
  8. **  Version 2.6 of 5-May-87.
  9. **
  10. **  This time logging selected header lines + more liberal parsing of
  11. **  the initial from-line but not yet with accounting & like; 14-Apr-85.
  12. **  Dbm lookup of UUCP domain names added 5-May-87.
  13. **
  14. **  The following definitions below are optional:
  15. **    LOGFILE -- If defined, should be the name of a file in which to
  16. **        log the raw addresses of each message.
  17. **    DEFAULT_HOST -- If no host is found in the envelope recipients,
  18. **        this host is assumed [defaults to your local host].
  19. **    DEFAULT_DOMAIN -- If the sending host is unqualifed, add this
  20. **        domain to the host for use in the Received: line.
  21. **    DOMAINTABLE -- If defined, should point to your local domain
  22. **        lookup database.  It is used for the same purpose as
  23. **        the DEFAULT_DOMAIN.
  24. */
  25.  
  26. #ifndef lint
  27. static char    Rcsid[] = "@(#)$Id: rmail.c,v 1.7 1991/07/01 17:28:32 paul Exp $";
  28. #endif /* !lint */
  29.  
  30. #include "sendmail.h"
  31.  
  32. #define DB_DIREXT    ".dir"
  33. #define DB_PAGEXT    ".pag"
  34.  
  35. #define STRSIZ        1024
  36. #define COMMA        ','
  37. /* #define LOGFILE        "/usr/lib/uucp/rmail.log" */
  38. #define SENDMAIL    "/usr/lib/sendmail"
  39. #define NETCHRS        "%@!:"
  40. /* #define DEFAULT_HOST    "liuida" */
  41. #define DEFAULT_DOMAIN    "UUCP"
  42. /* #define DOMAINTABLE    "/usr/lib/mail/domaintable" */
  43.  
  44. #define HH_CC        "cc"
  45. #define HH_FROM        "from"
  46. #define HH_MESSAGE_ID    "message_id"
  47. #define HH_RETURN_PATH    "return-path"
  48. #define HH_TO        "to"
  49. #define HH_VIA        "via"
  50.  
  51. #define MAKELC(C)    (isupper(C) ? tolower(C) : C)
  52. #define EATSPACE(P)    while (*P == ' ') P++
  53.  
  54. #ifdef __STDC__
  55. int anyin(const char *, const char *);
  56. int iskey(const char *, const char *);
  57. char * extract_address(char *, char *);
  58. #else /* !__STDC__ */
  59. # define    const
  60. int anyin();
  61. int iskey();
  62. char * extract_address();
  63. #endif /* __STDC__ */
  64. FILE *popen();
  65.  
  66. char *Progname;
  67. int Debug = FALSE;
  68. DBMFILE    *Dbm;
  69.  
  70. main(argc, argv)
  71.     int argc;
  72.     char **argv;
  73. {
  74.     char from_[STRSIZ], cmd[STRSIZ], s_mac[STRSIZ], f_opt[STRSIZ], s[STRSIZ];
  75.     char *v_opt = "";
  76.     char *p, *user, *host, *domain = "";
  77.     char *acctsys = (char *) getenv("ACCTSYS");
  78.     FILE *outf;
  79. #ifdef LOGFILE
  80.     FILE *logf = NULL;
  81. #endif /* LOGFILE */
  82. #ifdef DOMAINTABLE
  83.     datum key, val;
  84. #endif /* DOMAINTABLE */
  85.     int insideheader, printedlast = FALSE;
  86.     int c, errflg = FALSE;
  87.     
  88.     extern int optind;
  89.     extern char *optarg;
  90.  
  91. #ifdef DEFAULT_DOMAIN
  92.     domain = DEFAULT_DOMAIN;
  93. #endif /* DEFAULT_DOMAIN */
  94.  
  95.     Progname = argv[0];
  96.     while ((c = getopt(argc, argv, "D:dv")) != EOF) {
  97.     switch (c) {
  98.       case 'D':
  99.         domain = optarg;
  100.         break;
  101.       case 'd':
  102.         Debug++;
  103.         break;
  104.       case 'v':
  105.         v_opt = " -v";
  106.         break;
  107.       default:
  108.         errflg = TRUE;
  109.         break;
  110.     }
  111.     }
  112.     if (errflg || optind >= argc) {
  113.     (void) fprintf(stderr, "usage: %s [-Ddomain] user ...\n", Progname);
  114.     exit(2);
  115.     }
  116.  
  117.     /*
  118.      * set our real uid to root as well as our effective uid so
  119.      * make sendmail accept the -oM options
  120.      */
  121.     (void) setreuid(0, 0);
  122.  
  123. #ifdef DOMAINTABLE
  124.     Dbm = dbm_open(DOMAINTABLE, O_RDONLY);
  125.     if (Dbm == NULL)
  126.     perror(DOMAINTABLE);
  127. #endif /* DOMAINTABLE */
  128.  
  129. #ifdef LOGFILE
  130.     if ((logf = fopen(Debug ? "/dev/tty" : LOGFILE, "a")) != NULL) {
  131.     struct timeval t;
  132.     int a;
  133.  
  134.     (void) gettimeofday(&t, (struct timezone *) NULL);
  135.     (void) fprintf(logf, "\n[%.12s] ", ctime(&t.tv_sec) + 4);
  136.     for (a = 0; a < argc; a++)
  137.         (void) fprintf(logf, " '%s'", argv[a]);
  138.     (void) putc('\n', logf);
  139.     } else
  140.     (void) fprintf(stderr, "%s: couldn't open log file \"%s\"\n",
  141.                Progname, LOGFILE);
  142. #endif /* LOGFILE */
  143.  
  144.     user = NULL;
  145.     host = NULL;
  146.     (void) gets(from_);
  147.  
  148. #ifdef LOGFILE
  149.     if (logf != NULL)
  150.     (void) fprintf(logf, "%s\n", from_);
  151. #endif /* LOGFILE */
  152.  
  153.     if (strncmp(from_, "From ", 5) == 0 || strncmp(from_, ">From ", 6) == 0) {
  154.     user = index(from_, ' ') + 1;
  155.     EATSPACE(user);
  156.     if ((p = index(user, ' ')) != NULL) {
  157.         *p = '\0';
  158.         while ((p = index(p + 1, 'r')) != NULL) {
  159.         if (strncmp(p, "remote from ", 12) == 0) {
  160.             host = p + 12;
  161.             EATSPACE(host);
  162.             if ((p = index(host, '\n')) != NULL)
  163.             *p = '\0';
  164.             if (strcmp(host, "somewhere") == 0)
  165.             host = NULL;
  166.             break;
  167.         }
  168.         }
  169.     }
  170.     }
  171.  
  172.     if (acctsys == NULL)
  173.     acctsys = host;
  174.  
  175.     if (host)
  176.     (void) sprintf(f_opt, " -f%s!%s", host, user);
  177.     else if (user)
  178.     (void) sprintf(f_opt, " -f%s", user);
  179.     else
  180.     *f_opt = '\0';
  181.  
  182.     if (acctsys) {
  183. #ifdef DOMAINTABLE
  184.     if (Dbm != NULL) {
  185.         key.dptr = acctsys;
  186.         key.dsize = strlen(acctsys) + 1;
  187.         val = dbm_fetch(Dbm, key);
  188.         if (val.dptr != NULL)
  189.         acctsys = val.dptr;
  190.     }
  191. #endif /* DOMAINTABLE */
  192.     if (index(acctsys, '.') == NULL && *domain != '\0')
  193.         (void) sprintf(s_mac, " -oMs%s.%s", acctsys, domain);
  194.     else
  195.         (void) sprintf(s_mac, " -oMs%s", acctsys);
  196.     } else
  197.     *s_mac = '\0';
  198.  
  199.     (void) sprintf(cmd, "exec %s -ee -i -oMrUUCP%s%s%s",
  200.            SENDMAIL, s_mac, f_opt, v_opt);
  201.  
  202.     for (; optind < argc; optind++) {
  203.     (void) strcat(cmd, " '");
  204. #ifdef DEFAULT_HOST
  205.     if (anyin(argv[optind], NETCHRS) == NULL) {
  206.         (void) strcat(cmd, DEFAULT_HOST);
  207.         (void) strcat(cmd, "!");
  208.     }
  209. #endif /* DEFAULT_HOST */
  210.     if (*argv[optind] == '(')
  211.         (void) strncat(cmd, &argv[optind][1], strlen(argv[optind])-2);
  212.     else
  213.         (void) strcat(cmd, argv[optind]);
  214.     (void) strcat(cmd, "'");
  215.     }
  216.  
  217. #ifdef LOGFILE
  218.     if (logf != NULL)
  219.     (void) fprintf(logf, "%s\n", cmd);
  220. #endif /* LOGFILE */
  221.     if (Debug)
  222.     outf = stdout;
  223.     else {
  224.     outf = popen(cmd, "w");
  225.     if (outf == NULL) {
  226.         (void) fprintf(stderr, "%s: could not open pipe thru %s\n",
  227.                Progname, cmd);
  228.         exit(1);
  229.     }
  230.     }
  231.  
  232.     insideheader = TRUE;
  233.     while (gets(s)) {
  234.     if (*s == '\0')
  235.         insideheader = FALSE;
  236.  
  237. #ifdef LOGFILE
  238.     if (logf != NULL && insideheader &&
  239.         ((printedlast && isspace(*s)) ||
  240.          iskey(HH_FROM, s) || iskey(HH_TO, s) || iskey(HH_CC, s) ||
  241.          iskey(HH_RETURN_PATH, s) || iskey(HH_MESSAGE_ID, s))) {
  242.          (void) fprintf(logf, "\t%s\n", s);
  243.          printedlast = TRUE;
  244.          } else
  245.          printedlast = FALSE;
  246. #endif /* LOGFILE */
  247.     (void) fprintf(outf, "%s\n", s);
  248.     }
  249.  
  250. #ifdef LOGFILE
  251.     if (logf != NULL)
  252.     (void) fclose(logf);
  253. #endif /* LOGFILE */
  254.  
  255.     if (!Debug)
  256.     exit((pclose(outf) >> 8) & 0377);
  257. }
  258.  
  259. /*
  260. **    ANYIN -- Does the target string contain chars from the pattern string?
  261. */
  262. anyin(t, p)
  263.     const char *t;
  264.     register const char *p;
  265. {
  266.     for (; *p != '\0'; p++)
  267.     if (index(t, *p) != NULL)
  268.         return TRUE;
  269.     return FALSE;
  270. }
  271.  
  272. /*
  273. **    ISKEY -- Checks if the line is prefixed by the supplied keyword
  274. **    (immediately followed by a colon)
  275. */
  276. iskey(key, line)
  277.     const char *key, *line;
  278. {
  279.     for (; *key != '\0' && *line != '\0'; key++, line++)
  280.     if (MAKELC(*key) != MAKELC(*line))
  281.         break;
  282.  
  283.     return *key == '\0' && *line == ':';
  284. }
  285.  
  286. /*
  287. **    EXTRACT_ADDRESS -- Finds and extracts the machine address part
  288. **    of an address field.
  289. */
  290.  
  291. char *
  292. extract_address(field, address)
  293.     char *field, *address;
  294. {
  295.     char *address_start = address;
  296.  
  297.     while(*field && *field != COMMA && *field != '>')
  298.     switch (*field) {
  299.       case '<':
  300.         return extract_address(field, address_start);
  301.       case '(':
  302.         while (*field && *field != ')');
  303.         field++;
  304.         break;
  305.       case '"':
  306.         do
  307.         *address++ = *field++;
  308.         while (*field && *field != '"');
  309.         if (*field)
  310.         *address++ = *field++;
  311.         break;
  312.       case ' ':
  313.         *address++ = *field++;
  314.         EATSPACE(field);
  315.         break;
  316.       case '\\':
  317.         *address++ = *field++;
  318.         /* fall through */
  319.       default:
  320.         *address++ = *field++;
  321.     }
  322.     *address = '\0';
  323.     if (*field)
  324.     return index(field, COMMA)+1;
  325.     else
  326.     return field;
  327. }
  328.